package com.md.config.client;

import lombok.Data;
import org.apache.http.NoHttpResponseException;
import org.apache.http.conn.HttpHostConnectException;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.ResourceAccessException;

import java.util.HashMap;
import java.util.Map;

/**
 * @author 刘骄阳
 * 2023-10-12 15:19
 */
@Data
@ConfigurationProperties("client.retry")
@Configuration
public class RetryConfiguration {
  private static final int DEFAULT_RETRY_INTERVAL = 500;
  private static final double DEFAULT_RETRY_MAGNIFICATION = 1.5;
  private static final long DEFAULT_RETRY_MAX_WAIT = 5000L;
  private static final int DEFAULT_MAX_RETRY_SIZE = 3;
  /**
   * 指定重试异常类
   */
  private final Map<Class<? extends Throwable>, Boolean> retryAbleExceptions = new HashMap<>();
  /**
   * 最大尝试次数
   */
  private Integer maxRetrySize = DEFAULT_MAX_RETRY_SIZE;
  /**
   * 重试间隔时间
   */
  private Integer retryInterval = DEFAULT_RETRY_INTERVAL;
  /**
   * 倍率
   */
  private Double magnification = DEFAULT_RETRY_MAGNIFICATION;
  /**
   * 最大等待时间
   */
  private Long maxInterval = DEFAULT_RETRY_MAX_WAIT;

  public RetryConfiguration() {
    //服务端异常
    retryAbleExceptions.put(HttpServerErrorException.NotImplemented.class, true);
    retryAbleExceptions.put(HttpServerErrorException.BadGateway.class, true);
    retryAbleExceptions.put(HttpServerErrorException.ServiceUnavailable.class, true);
    // connection 异常
    retryAbleExceptions.put(HttpClientErrorException.NotFound.class, true);
    retryAbleExceptions.put(HttpHostConnectException.class, true);
    retryAbleExceptions.put(ResourceAccessException.class, true);
    retryAbleExceptions.put(NoHttpResponseException.class, true);
  }

  /**
   * 新增重试异常
   *
   * @param exception 异常
   */
  public void appendRetryException(final Class<? extends Throwable> exception) {
    retryAbleExceptions.put(exception, true);
  }

  /**
   * 移除要重试的异常
   *
   * @param exception 异常
   */
  public void removeRetryException(final Class<? extends Throwable> exception) {
    retryAbleExceptions.remove(exception);
  }
}
